简单贝塞尔曲线实现

您所在的位置:网站首页 unity 贝塞尔曲线 简单贝塞尔曲线实现

简单贝塞尔曲线实现

2023-06-18 13:52| 来源: 网络整理| 查看: 265

贝塞尔曲线:

似乎是在Windows XP的屏幕保护选项里面看到过贝塞尔曲线,一直对这个名字比较感兴趣,刚好最近想起来了便百度了一下。

参考:贝塞尔曲线扫盲 是当时第一次看的,讲的挺通俗易懂的;Wiki: wikipedia-Bézier curve ;绘制算法:  de Casteljau's 算法

学习过Photoshop,对里面的钢笔工具印象颇深,看到钢笔工具用的就是贝塞尔曲线的时候内心也是激动不已。

wiki中给出的数学公式还是蛮考研耐心的,不过后面的那个算法还是很容易描述的,大致思路:

  生成点

  枚举 0.001 - 1.000 的每个 T,获得T值对应的坐标:

    将生成的点集合从前到后依次连线

    在每条线段的t值处取新点

    将新的点集作为点集合重复上述操作直到只剩下一个点

    绘制剩下的这个点

其中的T值实际上就是一个位置,更具体的信息可以参考链接中的描述。

 

使用HTML5的canvas,通过JavaScript实现上述算法:

  大致思路上面也说过了,具体的话就是使用canvas的fillrect来绘制点了

  另外,由于JavaScript本身是单线程的,而我的程序需要一个死循环(随机嘛,不停地画曲线~),因此需要使用Worker进行多线程操作,它的逻辑就更简单了,主线程:

1 var worker = new Worker("caculatePoint.js"); 2 worker.postMessage(data);   子线程: 1 onmessage = function startHere(event) { 2   ... 3   postMessage(data); 4 }

看起来应该是相当易懂了。主线程通过另一个js文件创建新线程,发消息启动子线程,子线程发消息通知主线程。

 

实际效果(一次画6条贝塞尔曲线(尾首相连)然后清空画布):

 

 

 

JavaScript作业:

作业没什么好说的,主要是要画执行模型和对象模型的内存图,已经贴出,欢迎指正

需要注意的是,使用引入的iframe以及JavaScript时最好是在搭建好的服务器上运行,不然使用chrome浏览器运行时可能会出现错误,不过用ie,edge以及Firefox时没问题的。

由于贝塞尔曲线部分是JavaScript作业的一部分,因此详细代码包括 两个HTML文件,两个JS文件,一个css文件和几个图标。代码如下:

 

main.html:

1 DOCTYPE html> 2 3 4 5 6 20152480227_SJF 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 添加 23 替换 24 删除 25 插入 26 27 0 28 1 29 2 30 3 31 32 33 34 35 36 37 38 39 40 41 var width = 850, height = 720; 42 canvas = document.getElementById("canvas"); 43 ctx = canvas.getContext("2d"); 44 ctx.fillStyle = "#FF0000"; 45 46 var cnt = 0; 47 var worker = new Worker("caculatePoint.js"); 48 worker.postMessage(''); 49 worker.addEventListener('message', function (e) { 50 if (cnt != e.data.cnt) { 51 ctx.fillStyle = "#" + parseInt(Math.random() * 256).toString(16) + 52 parseInt(Math.random() * 256).toString(16) + 53 parseInt(Math.random() * 256).toString(16); 54 } 55 ctx.fillRect(e.data.x, e.data.y, 3, 3); 56 if (cnt != e.data.cnt && e.data.cnt % 6 == 0) { 57 ctx.fillStyle = "#FFFFFF"; 58 ctx.fillRect(0, 0, width, height); 59 ctx.fillStyle = "#ff0000" 60 } 61 cnt = e.data.cnt; 62 }, false); 63 64 65 66 67

iframe.html

1 DOCTYPE html> 2 3 4 5 6 7 8 JS Homework.JavaScript 大作业 9 10 11 You can choose to add, replace, delete or insert one paragraph when you have input your text. 12 增删改查随便选~ 13 14 15 Make sure you choose the right place if you do insertion. 16 插入段落时确保你已经选择了正确的序号~ 17 18 19 Empty input will be ignored! 20 不输入任何字符将不会产生任何操作! 21 22 23 24

 

main.js

 

1 var myifbody; 2 3 4 /** 5 * 启动时获取iframe的body 6 */ 7 window.onload = function init() { 8 myifbody = document.getElementById("myiframe").contentDocument.body; 9 } 10 11 /** 12 * 将 {@link #myokbutton} 的值替换为 s 13 * @param {string} s 待替换的字符串 14 */ 15 function setOKButtonText(s) { 16 document.getElementById("myokbutton").setAttribute("value", s); 17 } 18 19 /** 20 * 更改容纳canvas的div的visibility属性 21 */ 22 function changeCanvasVisibility() { 23 canvasdiv = document.getElementById("canvas"); 24 console.debug("double here"); 25 if (canvasdiv.style.visibility == "hidden") { 26 canvasdiv.style.visibility = "visible"; 27 } 28 else { 29 canvasdiv.style.visibility = "hidden"; 30 } 31 } 32 33 /** 34 * 点击 {@link #myokbutton} 时执行此函数 35 */ 36 function goHere() { 37 // text area 38 s = document.getElementById("myinput").value; 39 40 //radio input, know what to do(append, replace, delete, insert) 41 myradios = document.getElementsByName("myradio"); 42 cho = 0; 43 for (cho; cho < myradios.length; cho++) { 44 if (myradios[cho].checked) 45 break; 46 } 47 //ignore empty string 48 if (s.length exitTime) 7 return; 8 } 9 } 10 11 var cnt = 1; 12 function drawCurve(points, t) { 13 if (points.length == 1) { 14 // ctx.fillStyle = "#4F33DD"; 15 // document.write("" + "drawing: " + points[0].x + " " + points[0].y); 16 // ctx.fillRect(points[0].x, points[0].y, 1, 1); 17 var data = new Object(); 18 data.x = points[0].x; 19 data.y = points[0].y; 20 data.cnt = cnt; 21 this.postMessage(data); 22 sleep(1); 23 } 24 else { 25 newpoints = new Array(points.length - 1); 26 for (var i = 0; i < newpoints.length; i++) { 27 x = (1 - t) * points[i].x + t * points[i + 1].x; 28 y = (1 - t) * points[i].y + t * points[i + 1].y; 29 newpoints[i] = new Object(); 30 newpoints[i].x = x; 31 newpoints[i].y = y; 32 } 33 drawCurve(newpoints, t); 34 } 35 } 36 onmessage = function startHere(event) { 37 var width = 900, height = 750; 38 var n = 7; 39 var fir = new Object(), sec = new Object(); 40 fir.x = Math.random() * width; 41 fir.y = Math.random() * height; 42 sec.x = Math.random() * width; 43 sec.y = Math.random() * height; 44 while (true) { 45 var points = new Array(); 46 points[0] = fir; 47 points[1] = sec; 48 for (var i = 2; i < n; i++) { 49 var x = Math.random() * width; 50 var y = Math.random() * height; 51 points[i] = new Object(); 52 points[i].x = x; 53 points[i].y = y; 54 } 55 for (var t = 0.0001; t < 1; t += 0.0007) { 56 drawCurve(points, t); 57 } 58 cnt++; 59 fir.x = points[n - 1].x; fir.y = points[n - 1].y; 60 sec.x = points[n - 2].x; sec.y = points[n - 2].y; 61 } 62 }

 

main.css

1 @charset "utf-8"; 2 .my_iframe{ 3 box-shadow: lightgrey 1px 3px 5px; 4 border: none; 5 margin: 5px; 6 background:steelblue; 7 width: 1000px; 8 height: 450px; 9 } 10 .my_iframe_body{ 11 color: white; 12 font-family: Ubuntu Mono, '说说体'; 13 font-size: 23px; 14 } 15 .my_text_area{ 16 width: 995px; 17 height: 200px; 18 font-family: Ubuntu Mono, '说说体'; 19 display: block; 20 box-shadow: gray 1px 3px 5px; 21 font-size: 23px; 22 margin: 5px; 23 } 24 .my_bot_button{ 25 font-family: 说说体; 26 font-size: 19px; 27 float: left; 28 background: white; 29 padding: 10px; 30 margin-left: 5px; 31 display: block; 32 box-shadow: gray 1px 3px 5px; 33 } 34 .my_right_canvas{ 35 display: block; 36 box-shadow: gray 1px 3px 5px; 37 float: right; 38 margin-top: 5px; 39 margin-right: 20px 40 }

 

JS执行模型,对象模型,BOM以及DOM内存图:

 

 

 

JS作业内存图



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3